//
//  MyDocument.m
//  Rectiffy
//
//  Created by Jesper on 2007-07-14.
//  Copyright waffle software 2007 . All rights reserved.
//

#import "MyDocument.h"
#import "RectiffyController.h"

@implementation MyDocument

static NSString *selectionrepoCtx = @"selectionrepo";

- (id)init
{
    self = [super init];
    if (self) {
    
        // Add your subclass-specific initialization here.
        // If an error occurs here, send a [self release] message and return nil.
		repos = nil;
		theImage = nil;//[[NSImage imageNamed:@"NSApplicationIcon"] retain];
		viewingIntended = 1;
    }
    return self;
}

- (void)awakeFromNib {
	[repoController addObserver:self forKeyPath:@"selection" options:NSKeyValueObservingOptionNew context:selectionrepoCtx];	
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
	if (context == selectionrepoCtx) {
		if ([keyPath hasPrefix:@"selection"]) {
//			NSLog(@"selection changed");
			[self updateViewing];
		}
	} else {
		[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
	}
}

- (NSString *)windowNibName
{
    // Override returning the nib file name of the document
    // If you need to use a subclass of NSWindowController or if your document supports multiple NSWindowControllers, you should remove this method and override -makeWindowControllers instead.
    return @"MyDocument";
}

- (void)windowControllerDidLoadNib:(NSWindowController *) aController
{
    [super windowControllerDidLoadNib:aController];
    // Add any code here that needs to be executed once the windowController has loaded the document's window.
}

- (NSData *)dataRepresentationOfType:(NSString *)aType
{
    // Insert code here to write your document from the given data.  You can also choose to override -fileWrapperRepresentationOfType: or -writeToFile:ofType: instead.
    
    // For applications targeted for Tiger or later systems, you should use the new Tiger API -dataOfType:error:.  In this case you can also choose to override -writeToURL:ofType:error:, -fileWrapperOfType:error:, or -writeToURL:ofType:forSaveOperation:originalContentsURL:error: instead.
	return [theImage TIFFRepresentation];
}

//- (BOOL)loadDataRepresentation:(NSData *)data ofType:(NSString *)aType
- (BOOL)readFromData:(NSData *)data ofType:(NSString *)typeName error:(NSError **)outError
{
    NSImage *im = nil;
//	NSLog(@"load data... %d bytes, type: %@", [data length], typeName);
	im = [[NSImage alloc] initWithData:data];
	if (im == nil) {
//		NSLog(@"nope");
		// FIXME
		*outError = [NSError errorWithDomain:@"foo" code:1337 userInfo:nil];
		return NO;
	}
//	NSLog(@"yup");
	theImage = im;
	[self recalculateRepresentations];
    return YES;
}

NSString *FancyXByYStringLong(long x, long y) {
	if (x == NSImageRepMatchesDevice || y == NSImageRepMatchesDevice) {
		unichar infch = (unichar)0x221E;
		NSString *inf = [[NSString stringWithCharacters:&infch length:1] copy];
		return inf;
	}
	unichar ch = (unichar)0xD7;
	NSString *multi = [[NSString stringWithCharacters:&ch length:1] copy];
	return [NSString stringWithFormat:@"%d%@%d", x, multi, y];
}

NSString *FancyXByYStringSize(NSSize size) {
	if ((size.width == floor(size.width)) && (size.height == floor(size.height))) {
		return FancyXByYStringLong((long)size.width, (long)size.height);
	}
	unichar ch = (unichar)0xD7;
	NSString *multi = [[NSString stringWithCharacters:&ch length:1] copy];
	return [NSString stringWithFormat:@"%.02f%@%.02f", size.width, multi, size.height];
}

NSString *TypeFromClassName(NSString *cn) {
	if ([cn hasPrefix:@"NSBitmap"] || [cn hasPrefix:@"NSPICT"]) {
		return @"Bitmap";
	} else if ([cn hasPrefix:@"NSPDF"] || [cn hasPrefix:@"NSEPS"]) {
		return @"Vector";
	} else {
		return [NSString stringWithFormat:@"?: %@", cn];
	}
}

NSString *ReadableColorSpaceName(NSString *csn) {
	if ([csn isEqualToString:NSCalibratedBlackColorSpace]) {
		return @"Calibrated Black";
	}
	if ([csn isEqualToString:NSCalibratedRGBColorSpace]) {
		return @"Calibrated RGB";
	}
	if ([csn isEqualToString:NSCalibratedWhiteColorSpace]) {
		return @"Calibrated White";
	}
	if ([csn isEqualToString:NSDeviceBlackColorSpace]) {
		return @"Device Black";
	}
	if ([csn isEqualToString:NSDeviceRGBColorSpace]) {
		return @"Device RGB";
	}
	if ([csn isEqualToString:NSDeviceWhiteColorSpace]) {
		return @"Device White";
	}
	if ([csn isEqualToString:NSDeviceCMYKColorSpace]) {
		return @"Device CMYK";
	}
	if ([csn isEqualToString:NSNamedColorSpace]) {
		return @"Named colors";
	}
	if ([csn isEqualToString:NSPatternColorSpace]) {
		return @"Pattern color";
	}
	if ([csn isEqualToString:NSCustomColorSpace]) {
		return @"Custom color space";
	}
	return @"Unknown";
}

- (void)recalculateRepresentations {
	[self willChangeValueForKey:@"representations"];
	if (nil == repos) {
		repos = [[NSMutableArray array] retain];
	} else {
		[repos removeAllObjects];
	}
//	NSLog(@"image: %@", theImage);
	
	if ([[theImage representations] count] > 0) {
	NSEnumerator *repoEnumerator = [[theImage representations] objectEnumerator];
	NSImageRep *repo;
	float factor = [[NSScreen mainScreen] userSpaceScaleFactor];
	while (repo = [repoEnumerator nextObject]) {
		NSMutableDictionary *dict = [NSMutableDictionary dictionary];
		
		NSSize size = [repo size];
		
		NSString *pixelDim = FancyXByYStringLong([repo pixelsWide], [repo pixelsHigh]);
		NSString *actualDim = FancyXByYStringSize(size);
		
		[dict setObject:[NSString stringWithFormat:@"%@ - %@", TypeFromClassName([repo className]), pixelDim] forKey:@"listLabel"];
		
		NSImage *im = [[NSImage alloc] initWithSize:size];
		[im addRepresentation:repo];
		[dict setObject:im forKey:@"image"];
		
		NSImage *impfp = [[NSImage alloc] initWithSize:size];
		NSImageRep *repo2 = [repo copy];
		[repo2 setSize:NSMakeSize([repo2 pixelsWide],[repo2 pixelsHigh])];
		[impfp setSize:NSMakeSize([repo2 pixelsWide],[repo2 pixelsHigh])];
		[impfp addRepresentation:repo2];
		[dict setObject:impfp forKey:@"pixelForPixelImage"];
		if ([repo2 pixelsWide] != NSImageRepMatchesDevice) {
			double ratio2 = ([repo2 pixelsWide]/size.width);
			double dpi2 = ratio2*factor*72.0;
//			NSLog(@"pixel for pixel dpi: %@", [NSString stringWithFormat:@"%.02f", dpi2]);
		}
		
		[dict setObject:actualDim forKey:@"actualDim"];
		[dict setObject:pixelDim forKey:@"pixelDim"];
		
		[dict setObject:ReadableColorSpaceName([repo colorSpaceName]) forKey:@"colorSpace"];
		if ([repo pixelsWide] != NSImageRepMatchesDevice) {
			double ratio = ([repo pixelsWide]/size.width);
			double dpi = ratio*factor*72.0;
			[dict setObject:[NSString stringWithFormat:@"%.02f", dpi] forKey:@"dpi"];
		} else {
			unichar infch = (unichar)0x221E;
			NSString *inf = [[NSString stringWithCharacters:&infch length:1] copy];	
			[dict setObject:inf forKey:@"dpi"];
		}
		
		[repos addObject:dict];
		
		aspectRatio = (size.width / size.height);
//		NSLog(@"repo: %@", dict);
	} 
	} else {
		aspectRatio = -1.0;
		theImage = nil;
	}
	[self didChangeValueForKey:@"representations"];
}

- (NSArray *)representations {
	if (nil == repos) {
		[self recalculateRepresentations];
	}
	return repos;
}

- (NSImage *)viewingImage {
	if (viewingIntended == 1) {
		// image
//		NSLog(@"returning image");
		return [repoController valueForKeyPath:@"selection.image"];
	} else {
		// pixelForPixelImage
//		NSLog(@"returning pixel for pixel image");
		return [repoController valueForKeyPath:@"selection.pixelForPixelImage"];
	}
}

- (void)updateViewing {
	[[RectiffyController sharedController] updateViewingIntendedMenus];
	[self willChangeValueForKey:@"viewingImage"];
	[self didChangeValueForKey:@"viewingImage"];
}

- (void)windowDidBecomeKey:(NSNotification *)aNotification {
	[[RectiffyController sharedController] updateViewingIntendedMenus];
}

- (void)setViewingIntended:(int)vi {
	viewingIntended = vi;
	[self updateViewing];
}

- (int)viewingIntended {
	return viewingIntended;
}

- (IBAction)addRep:(id)sender {
	NSOpenPanel *op = [NSOpenPanel openPanel];
	[op setCanChooseFiles:YES];
	[op setCanChooseDirectories:NO];
	NSLog(@"allowed: %@", [NSImage imageFileTypes]);
	[op setAllowedFileTypes:[NSImage imageFileTypes]];
	[op setAllowsMultipleSelection:YES];
	[op setDelegate:self];
	if (NSFileHandlingPanelOKButton == [op runModal]) {
		NSArray *urls = [op URLs];
		NSEnumerator *urlsEnumerator = [urls objectEnumerator];
		NSURL *url;
		BOOL changed = NO;
		while (url = [urlsEnumerator nextObject]) {
			NSImage *im = [[NSImage alloc] initWithContentsOfURL:url];
			if (nil != im) {
				if (nil != theImage) {
					[theImage addRepresentations:[im representations]];
				} else {
					theImage = [[NSImage alloc] init];
					[theImage addRepresentations:[im representations]];
					[theImage setSize:[[[im representations] objectAtIndex:0] size]];
				}
				changed = YES;
			}			
		} 
		if (changed) {
			[self recalculateRepresentations];
		}
	}
}

- (BOOL)panel:(id)sender isValidFilename:(NSString *)filename {
//	if (isFilteringToAspectRatio) {
	NSOpenPanel *op = sender;
		NSImage *im = [[NSImage alloc] initWithContentsOfFile:filename];
		NSLog(@"filename: %@", filename);
		double aspectRatioThis = ([im size].width / [im size].height);
		NSLog(@"aspectRatio: %f, this: %f", aspectRatio, aspectRatioThis);
		if (aspectRatio == aspectRatioThis || aspectRatio == -1.0) {
			return YES;
		}
		[[NSAlert alertWithMessageText:[NSString stringWithFormat:@"The image %@ has the wrong aspect ratio.", [filename lastPathComponent]] defaultButton:@"OK" alternateButton:nil otherButton:nil informativeTextWithFormat:@"Rectiffy couldn't add the image %@ because its aspect ratio (width-height ratio) is different from the other representations.\n\nThe aspect ratio of the new image is %.04f. The aspect ratio of the existing image is %.04f.", filename, aspectRatioThis, aspectRatio] beginSheetModalForWindow:op modalDelegate:self didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) contextInfo:NULL];
		return NO;
/*	} else {
		return YES;
	}*/
}
- (void)alertDidEnd:(NSAlert *)alert returnCode:(int)returnCode contextInfo:(void *)contextInfo {
	[[alert window] orderOut:self];
}

- (IBAction)removeRep:(id)sender {
	NSIndexSet *indices = [repoController selectionIndexes];
	if ([indices count] == 0) return;
	NSMutableIndexSet *mis = [indices mutableCopy];
	while (([mis lastIndex] != NSNotFound)) {
		unsigned int lastIndex = [mis lastIndex];
		[theImage removeRepresentation:[[theImage representations] objectAtIndex:lastIndex]];
		[mis removeIndex:lastIndex];
	}
	[repoController removeSelectionIndexes:indices];
	[self recalculateRepresentations];
}

@end
